package com.lute.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import org.springframework.security.oauth2.common.json.JSONArray;
import org.springframework.security.oauth2.common.json.JSONException;
import org.springframework.security.oauth2.common.json.JSONObject;

import com.lute.json.UserNameJSON;
import com.lute.utils.DAOFactory;

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="User_Type", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("User")
public class User implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	private int id_user;
	private String first_name;
	private String last_name;
	private String login;
	private String email;
	private String accountLocked = UserAccountState.ACTIVE.toString();
	private Role role;
	
	public User() {}
	public User(String firstName, String lastName, String login, String email, Role role) {
		this.first_name = firstName;
		this.last_name = lastName;
		this.login = login;
		this.email = email;
		this.role = role;
	}

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	public int getId_user() {
		return id_user;
	}	
	
	public void setId_user(int id_user) {
		this.id_user = id_user;
	}
	
	public String getFirst_name() {
		return first_name;
	}
	
	public void setFirst_name(String first_name) {
		this.first_name = first_name;
	}
	
	public String getLast_name() {
		return last_name;
	}
	
	public void setLast_name(String last_name) {
		this.last_name = last_name;
	}
	
	public String getLogin() {
		return login;
	}
	
	public void setLogin(String login) {
		this.login = login;
	}

	@ManyToOne(cascade = {CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.REMOVE})
	@JoinColumn(name="id_role")
	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}
	
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
	
	public String getAccountLocked() {
		return accountLocked;
	}
	public void setAccountLocked(String accountLocked) {
		this.accountLocked = accountLocked;
	}
	
	public static JSONArray calculateCreativeHours(EmployeeProfile employeeProfile, JSONArray calendarEntries,
												   float workedHours,int numberOfDays) throws JSONException {
		float percentage = 0;
		int creativityPercentage = 0;
		int creativeHours = 0;
		int modulo = 0;
		int portionOfCreativeHours = 0;
		int totalPart = 0; 
		
		creativityPercentage =  employeeProfile.getPositions().getCreativity_percentage();
				
		percentage = (workedHours * creativityPercentage)/100;
				
		if( ((int)(percentage + 0.5)) > (int)percentage ) {
			creativeHours = ((int)percentage) + 1;
		} else {
			creativeHours = (int)percentage;
		}

		modulo = creativeHours % numberOfDays;
		
		/* clear creative hours before calculating */
		for(int i=0; i<calendarEntries.length(); i++) {
			String companyCategory =  calendarEntries.getJSONObject(i).getString("companyCategory");
			if(((companyCategory.equals("workClient")) || (companyCategory.equals("workCompany"))) ) {
				calendarEntries.getJSONObject(i).put("creativeHours", 0);
			}
		}
		
		if(modulo > 0) {
			totalPart = creativeHours/numberOfDays;
			if(totalPart == 0) {
				for(int i=0; i<calendarEntries.length(); i++) {
					String companyCategory =  calendarEntries.getJSONObject(i).getString("companyCategory");
					if(((companyCategory.equals("workClient")) || (companyCategory.equals("workCompany"))) ) {
						if(i < creativeHours)calendarEntries.getJSONObject(i).put("creativeHours", 1);
					}
				}
			} else {
				int hoursAmount = creativeHours;
				int iter = 0;
				
				while(hoursAmount > 0) {
					String companyCategory =  calendarEntries.getJSONObject(iter).getString("companyCategory");
					if(((companyCategory.equals("workClient")) || (companyCategory.equals("workCompany"))) ) {
						int hours = calendarEntries.getJSONObject(iter).getInt("hours");
						int temp = calendarEntries.getJSONObject(iter).getInt("creativeHours");
						if(hours > temp) {
							calendarEntries.getJSONObject(iter).put("creativeHours", temp + 1);
							hoursAmount--;
						}
					}
					iter++;
					if(iter == (calendarEntries.length())) iter = 0;
				}

			}
		} else {
			portionOfCreativeHours = creativeHours / numberOfDays;
			//System.out.println("portionOfCreativeHours"+portionOfCreativeHours);
			int diff = portionOfCreativeHours;
			for(int i=0; i<calendarEntries.length(); i++) {
				String companyCategory =  calendarEntries.getJSONObject(i).getString("companyCategory");
				if(((companyCategory.equals("workClient")) || (companyCategory.equals("workCompany"))) ) {
					int hours = calendarEntries.getJSONObject(i).getInt("hours");
					if(portionOfCreativeHours < hours) {
						calendarEntries.getJSONObject(i).put("creativeHours", diff);
					} else {
						calendarEntries.getJSONObject(i).put("creativeHours", hours);
						diff += (portionOfCreativeHours - hours);
					}
				}
			}
		}
		
		return calendarEntries;
	}
	
	public static User getUserFromDB(String propertyName, int propertyValue) {
		User user = DAOFactory.getInstance().getLuteInterface().getUserFromDataBaseByUserId(propertyName, propertyValue);
		return user;
	}
	
	public static User getUserFromDB(String propertyName, String propertyValue) {
		User user = DAOFactory.getInstance().getLuteInterface().getUserFromDataBase(propertyName, propertyValue);
		return user;
	}
	
	public static List<User> getUsersFromDB() {
		return DAOFactory.getInstance().getLuteInterface().getUsersFromDataBase();
	}
	
	public static List<User> getUsersFromDB(String propertyName, int userRole) {
		return DAOFactory.getInstance().getLuteInterface().getUsersByUserRoleFromDataBase(propertyName, userRole);
	}
	
	public static List<User> getUsersFromDB(String propertyName1,String propertyValue1,
											String propertyName2, String propertyValue2) {
		return DAOFactory.getInstance().getLuteInterface().getUsersFromDataBase(propertyName1, propertyValue1, 
																				propertyName2, propertyValue2);
	}
	
	public static List<User> getUsersFromDB(String propertyName, String propertyValue) {
		return DAOFactory.getInstance().getLuteInterface().getUsersFromDataBase(propertyName, propertyValue);
	}
	
	public static List<User> getEmployeesAndApproversFromDB(String propertyName, String propertyValue) {
		return DAOFactory.getInstance().getLuteInterface().getEmployeesAndApproversFromDataBase(propertyName, propertyValue);
	}
	
	public static void addUserToDB(User user) {
		DAOFactory.getInstance().getLuteInterface().addObjectToDataBase(user);
	}
	
	public static void updateUserInDB(User user) {
		DAOFactory.getInstance().getLuteInterface().updateObjectinDataBase(user);
	}
	
	public static List<UserNameJSON> prepareUsersCredentials() {
		List<UserNameJSON> usersName = new ArrayList<UserNameJSON>();
		List<User> users = getUsersFromDB();
		UserNameJSON userNameJSON = null;		
		for(int i = 0;  i < users.size(); i++) {
			userNameJSON = new UserNameJSON();
			userNameJSON.setFirstName(users.get(i).getFirst_name());
			userNameJSON.setLastName(users.get(i).getLast_name());
			userNameJSON.setEmail(users.get(i).getEmail());
			usersName.add(userNameJSON);
		}
		return usersName;
	}
	
	public static Client getClientWithAccPeriodByIdFromDB(String propertyName, int propertyValue) {
		return DAOFactory.getInstance().getLuteInterface().getClientWithAccPeriodByIdFromDataBase(propertyName, propertyValue);
	}

	
	public static List<UserNameJSON> prepareUsersCredentials(List<User> users) {
		List<UserNameJSON> usersName = new ArrayList<UserNameJSON>();
		UserNameJSON userNameJSON = null;
		for(int i =0;  i < users.size(); i++) {
			userNameJSON = new UserNameJSON();
			userNameJSON.setFirstName(users.get(i).getFirst_name());
			userNameJSON.setLastName(users.get(i).getLast_name());
			userNameJSON.setEmail(users.get(i).getEmail());
			usersName.add(userNameJSON);
		}
		return usersName;
	}
	
	public static String checkUserRole(int userId) {
		User user = DAOFactory.getInstance().getLuteInterface().getUserFromDataBaseByUserId("id_user", userId);
		String role = user.getRole().getName();
		return role;
	}
	
	public static List<JSONObject> findUsersBySpecifiedParams(List<User> users, int numberParamToCheck,JSONObject jsonReq, List<JSONObject> basicUserData) throws JSONException  {
		
		for(User user: users) {
			
			int isAllPassed = numberParamToCheck;
			
			JSONObject tempObject = new JSONObject();
			tempObject.put("userFirstName", user.getFirst_name());
			tempObject.put("userLastName", user.getLast_name());
			tempObject.put("userId", user.getId_user());
			tempObject.put("userRole",user.getRole().getName());
			tempObject.put("clientId",JSONObject.NULL);
			tempObject.put("accountLocked",JSONObject.NULL);
			
			if(user.getRole().getName().equals("clientAdmin")) {
				ClientAdminProfile caProfile = ClientAdminProfile.
						getClientAdminProfileByClientAdminIdWithClientsFromDB(user.getId_user());
				tempObject.put("clientId", caProfile.getDefaultClientId());
				if(!(jsonReq.isNull("clientId"))) {
					String str = jsonReq.getString("clientId");
					int clientId = Integer.parseInt(str);
					List<Client> clients = caProfile.getClients();
					for(Client client: clients) {
						if(client.getId_client() == clientId) {
							tempObject.put("clientId",clientId);
							isAllPassed--;
						}
					}
				}
			}
			
			if(!(jsonReq.isNull("userFirstName"))) {
				if(jsonReq.getString("userFirstName").equals(user.getFirst_name())) {
					isAllPassed--;
				}
			}
			
			if(!(jsonReq.isNull("userLastName"))) {
				if(jsonReq.getString("userLastName").equals(user.getLast_name())) {
					isAllPassed--;
				}
			}
			
			if(!(jsonReq.isNull("userRole"))) {
				if(jsonReq.getString("userRole").equals(user.getRole().getName())) {
					isAllPassed--;
				}
			}
			
			if(user.getAccountLocked().equals(UserAccountState.ACTIVE.toString())) {
				tempObject.put("accountLocked", false);
			} else {
				tempObject.put("accountLocked", true);
			}
			if(!(jsonReq.isNull("userAccountState"))) {
				if(user.getAccountLocked().equals(jsonReq.getString("userAccountState"))) {
					isAllPassed--;
				}
			}
			if(isAllPassed == 0) {
				basicUserData.add(tempObject);
			}
		}
		return basicUserData;
	}
	
	public static List<JSONObject> findEmployeesBySpecifiedParams(List<EmployeeProfile> profiles,
																 Integer clientId, 
																 int numberParamToCheck,
																 JSONObject jsonReq) throws JSONException {
		
		List<JSONObject> basicUserData = new ArrayList<JSONObject>();
		
		System.out.println("N"+numberParamToCheck);
		
		for(EmployeeProfile profile: profiles) {
			
			int isAllPassed = numberParamToCheck;
			
			JSONObject tempObject = new JSONObject();
			tempObject.put("accountLocked", JSONObject.NULL);
			tempObject.put("employeeAccountingPeriodState", JSONObject.NULL);
			tempObject.put("employeePosition", JSONObject.NULL);
			tempObject.put("businessUnitId", JSONObject.NULL);
			tempObject.put("employeeState", JSONObject.NULL);
			
			if(!(clientId == null)) {
				/* approver */
				if(profile.getEmployee() == null) {
					if(!(profile.getApprover().getApproverProfile().getClient().getId_client() == clientId)) {
						continue;
					} else {
						isAllPassed--;
					}
				} else {
					if(!(profile.getEmployee().getEmployeeProfil().getClient().getId_client() == clientId)) {
						continue;
					} else {
						isAllPassed--;
					}
				}
			}
			
			if(profile.getEmployee() == null) {
				EmployeeAccountingPeriod employeeAccPeriod = EmployeeAccountingPeriod.
						getCurrentEmployeeAccPeriod("approver", profile.getApprover().getId_user());
				tempObject.put("employeeAccountingPeriodState", employeeAccPeriod.getEmployeeAccountingPeriodState());
				//TODO What about null ? It means no open calendar is available ?
				if(!(jsonReq.isNull("employeeAccountingPeriodState"))) {
					if(employeeAccPeriod.getEmployeeAccountingPeriodState().equals(jsonReq.getString("employeeAccountingPeriodState"))) {
						isAllPassed--;
					}
				}
			} else {
				EmployeeAccountingPeriod employeeAccPeriod = EmployeeAccountingPeriod.
						getCurrentEmployeeAccPeriod("employee", profile.getEmployee().getId_user());
				tempObject.put("employeeAccountingPeriodState", employeeAccPeriod.getEmployeeAccountingPeriodState());
				
				if(!(jsonReq.isNull("employeeAccountingPeriodState"))) {
					if(employeeAccPeriod.getEmployeeAccountingPeriodState().equals(jsonReq.getString("employeeAccountingPeriodState"))) {
						tempObject.put("employeeAccountingPeriodState", employeeAccPeriod.getEmployeeAccountingPeriodState());
						isAllPassed--;
					}
				}
			}
			/* approver */
			if(profile.getEmployee() == null) {		
				if(!(jsonReq.isNull("userFirstName"))) {
					if(profile.getApprover().getFirst_name().equals(jsonReq.getString("userFirstName"))) {
						isAllPassed--;
					}
				}
			} else {
				if(!(jsonReq.isNull("userFirstName"))) {
					if(profile.getEmployee().getFirst_name().equals(jsonReq.getString("userFirstName"))) {
						isAllPassed--;
					}
				}
			}
			/* approver */
			if(profile.getEmployee() == null) {
				if(!(jsonReq.isNull("userLastName"))) {
					if(profile.getApprover().getLast_name().equals(jsonReq.getString("userLastName"))) {
						isAllPassed--;
					}
				}
			} else {
				if(!(jsonReq.isNull("userLastName"))) {
					if(profile.getEmployee().getLast_name().equals(jsonReq.getString("userLastName"))) {
						isAllPassed--;
					}
				}
			}
			/* approver */
			if(profile.getEmployee() == null) {
				if(!(jsonReq.isNull("employeePosition"))) {
					if(profile.getPositions().getName().equals(jsonReq.getString("employeePosition"))) {
						isAllPassed--;
					}
				}
			} else {
				if(!(jsonReq.isNull("employeePosition"))) {
					if(profile.getPositions().getName().equals(jsonReq.getString("employeePosition"))) {
						isAllPassed--;
					}
				}
			}
			/* approver */
			if(profile.getEmployee() == null) {
				if(!(jsonReq.isNull("businessUnitId"))) {
					if(profile.getBusinessUnit().getName().equals(jsonReq.getString("businessUnitId"))) {
						isAllPassed--;
					}
				}
			} else {
				if(!(jsonReq.isNull("businessUnitId"))) {
					if(profile.getBusinessUnit().getName().equals(jsonReq.getString("businessUnitId"))) {
						isAllPassed--;
					}
				}
			}
			/* approver */
			if(profile.getEmployee() == null) {
				if(!(jsonReq.isNull("employeeState"))) {
					if(profile.getEmployeeCurrentState().equals(jsonReq.getString("employeeState"))) {
						isAllPassed--;
					}
				}
			} else {
				if(!(jsonReq.isNull("employeeState"))) {
					if(profile.getEmployeeCurrentState().equals(jsonReq.getString("employeeState"))) {
						tempObject.put("employeeState",profile.getEmployeeCurrentState());
						isAllPassed--;
					}
				}
			}
			/* approver */
			if(profile.getEmployee() == null) {
				if(!(jsonReq.isNull("userRole"))) {
					if(profile.getApprover().getRole().getName().equals(jsonReq.getString("userRole"))) {
						isAllPassed--;
					}
				}
			} else {
				if(!(jsonReq.isNull("userRole"))) {
					if(profile.getEmployee().getRole().getName().equals(jsonReq.getString("userRole"))) {
						isAllPassed--;
					}
				}
			}
			/* approver */
			if(profile.getEmployee() == null) {
				if(profile.getApprover().getAccountLocked().equals(UserAccountState.ACTIVE.toString())) {
					tempObject.put("accountLocked", false);
				} else {
					tempObject.put("accountLocked", true);
				}
				if(!(jsonReq.isNull("userAccountState"))) {
					if(profile.getApprover().getAccountLocked().equals(jsonReq.getString("userAccountState"))) {
						isAllPassed--;
					}
				}
			} else {
				if(profile.getEmployee().getAccountLocked().equals(UserAccountState.ACTIVE.toString())) {
					tempObject.put("accountLocked", false);
				} else {
					tempObject.put("accountLocked", true);
				}
				if(!(jsonReq.isNull("userAccountState"))) {
					if(profile.getEmployee().getAccountLocked().equals(jsonReq.getString("userAccountState"))) {
						isAllPassed--;
					}
				}
			}
			
			
			/* all params have been passed ? */
			if(isAllPassed == 0) {
				tempObject.put("employeePosition",profile.getPositions().getName());
				tempObject.put("businessUnitId",profile.getBusinessUnit().getId_business_unit());
				tempObject.put("employeeState",profile.getEmployeeCurrentState());
				/* approver */
				if(profile.getEmployee() == null) {
					tempObject.put("userFirstName",profile.getApprover().getFirst_name());
					tempObject.put("userLastName",profile.getApprover().getLast_name());
					tempObject.put("approverId", profile.getApprover().getId_user());
					tempObject.put("userId", profile.getApprover().getId_user());
					tempObject.put("userRole",profile.getApprover().getRole().getName());
					tempObject.put("clientId", profile.getApprover().getApproverProfile().getClient().getId_client());
					tempObject.put("creativeHoursPercentage", profile.getApprover().getApproverProfile().getPositions().getCreativity_percentage());
					basicUserData.add(tempObject);
				} else {
					tempObject.put("userFirstName",profile.getEmployee().getFirst_name());
					tempObject.put("userLastName",profile.getEmployee().getLast_name());
					tempObject.put("approverId", profile.getEmployeeApprover());
					tempObject.put("userId", profile.getEmployee().getId_user());
					tempObject.put("userRole",profile.getEmployee().getRole().getName());
					tempObject.put("clientId", profile.getEmployee().getEmployeeProfil().getClient().getId_client());
					tempObject.put("creativeHoursPercentage", profile.getEmployee().getEmployeeProfil().getPositions().getCreativity_percentage());
					basicUserData.add(tempObject);
				}
			}
		}
		return basicUserData;
	}
}
